using System;
using System.Collections.Generic;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace TxTReader.Core
{
    /// <summary>
    /// 基于内存映射的高效文件读取器
    /// </summary>
    public class MemoryMappedFileReader : IFileReader, IDisposable
    {
        private MemoryMappedFile? _mmf;
        private MemoryMappedViewAccessor? _accessor;
        private readonly Dictionary<int, long> _linePositions;
        private readonly Dictionary<int, int> _lineLengths;
        private readonly int _maxCacheSize = 10000; // 缓存10000行的位置信息
        private long _fileSize;
        private Encoding _currentEncoding = Encoding.UTF8;
        private bool _disposed = false;
        private bool _linePositionsBuilt = false;
        private string? _cachedContent; // 缓存文件内容

        public string FilePath { get; private set; } = string.Empty;
        public Encoding CurrentEncoding => _currentEncoding;
        public long TotalLines { get; private set; } = -1;
        public bool IsFileOpen => _mmf != null && !_disposed;

        public event EventHandler<EncodingChangedEventArgs>? EncodingChanged;
        public event EventHandler<FileOpenedEventArgs>? FileOpened;

        public MemoryMappedFileReader()
        {
            _linePositions = new Dictionary<int, long>();
            _lineLengths = new Dictionary<int, int>();
        }

        /// <summary>
        /// 打开文件
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <param name="encoding">指定编码，null表示自动检测</param>
        public async Task<bool> OpenFileAsync(string filePath, Encoding? encoding = null)
        {
            try
            {
                System.Diagnostics.Debug.WriteLine($"MemoryMappedFileReader.OpenFileAsync: 开始打开文件 {filePath}");
                CloseFile();

                if (!File.Exists(filePath))
                {
                    System.Diagnostics.Debug.WriteLine($"MemoryMappedFileReader.OpenFileAsync: 文件不存在 {filePath}");
                    return false;
                }

                FilePath = filePath;
                _fileSize = new FileInfo(filePath).Length;
                System.Diagnostics.Debug.WriteLine($"MemoryMappedFileReader.OpenFileAsync: 文件大小 = {_fileSize}");

                // 检测编码
                if (encoding == null)
                {
                    _currentEncoding = EncodingDetector.DetectFileEncoding(filePath);
                }
                else
                {
                    _currentEncoding = encoding;
                }
                System.Diagnostics.Debug.WriteLine($"MemoryMappedFileReader.OpenFileAsync: 检测到编码 = {_currentEncoding.EncodingName}");

                // 创建内存映射文件
                System.Diagnostics.Debug.WriteLine($"MemoryMappedFileReader.OpenFileAsync: 开始创建内存映射文件");
                _mmf = MemoryMappedFile.CreateFromFile(filePath, FileMode.Open, null, _fileSize, MemoryMappedFileAccess.Read);
                System.Diagnostics.Debug.WriteLine($"MemoryMappedFileReader.OpenFileAsync: 内存映射文件创建成功");
                
                _accessor = _mmf.CreateViewAccessor(0, _fileSize, MemoryMappedFileAccess.Read);
                System.Diagnostics.Debug.WriteLine($"MemoryMappedFileReader.OpenFileAsync: 访问器创建成功");

                // 构建行位置索引
                System.Diagnostics.Debug.WriteLine($"MemoryMappedFileReader.OpenFileAsync: 开始构建行位置索引");
                await BuildLinePositionsAsync();
                System.Diagnostics.Debug.WriteLine($"MemoryMappedFileReader.OpenFileAsync: 行位置索引构建完成，总行数 = {TotalLines}");

                OnFileOpened(new FileOpenedEventArgs(filePath, _currentEncoding, TotalLines));
                System.Diagnostics.Debug.WriteLine($"MemoryMappedFileReader.OpenFileAsync: 文件打开成功");
                return true;
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"MemoryMappedFileReader.OpenFileAsync: 异常 - {ex.GetType().Name}: {ex.Message}");
                System.Diagnostics.Debug.WriteLine($"MemoryMappedFileReader.OpenFileAsync: 堆栈跟踪 - {ex.StackTrace}");
                CloseFile();
                throw new FileReaderException($"打开文件失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 构建行位置索引
        /// </summary>
        private async Task BuildLinePositionsAsync()
        {
            if (_accessor == null) return;

            _linePositions.Clear();
            _lineLengths.Clear();

            await Task.Run(() =>
            {
                // 快速统计行数，不加载完整内容
                int lineCount = 0;
                long position = 0;
                
                var buffer = new byte[1024 * 1024]; // 1MB缓冲区
                long bytesRead = 0;
                
                while (bytesRead < _fileSize)
                {
                    int bytesToRead = (int)Math.Min(buffer.Length, _fileSize - bytesRead);
                    _accessor.ReadArray(bytesRead, buffer, 0, bytesToRead);
                    
                    for (int i = 0; i < bytesToRead; i++)
                    {
                        if (buffer[i] == '\n')
                        {
                            lineCount++;
                        }
                    }
                    
                    bytesRead += bytesToRead;
                }
                
                // 检查最后一行是否有换行符
                var lastByte = new byte[1];
                _accessor.ReadArray(_fileSize - 1, lastByte, 0, 1);
                if (lastByte[0] != '\n')
                {
                    lineCount++; // 没有换行符的最后一行
                }
                
                TotalLines = lineCount;
                _linePositionsBuilt = true;
            });
        }

        /// <summary>
        /// 直接读取文件内容
        /// </summary>
        /// <returns>文件内容</returns>
        private string ReadFileContentDirectly()
        {
            if (_accessor == null || _fileSize == 0) return string.Empty;

            try
            {
                // 读取整个文件内容
                var buffer = new byte[_fileSize];
                int bytesRead = _accessor.ReadArray(0, buffer, 0, (int)_fileSize);
                
                // 使用检测到的编码解码
                return _currentEncoding.GetString(buffer, 0, bytesRead);
            }
            catch
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// 获取指定行
        /// </summary>
        /// <param name="lineNumber">行号（从1开始）</param>
        /// <returns>文本行</returns>
        public async Task<TextLine?> GetLineAsync(int lineNumber)
        {
            if (!IsFileOpen || lineNumber < 1 || lineNumber > TotalLines)
                return null;

            return await Task.Run(() =>
            {
                try
                {
                    // 按需读取指定行
                    var line = ReadLineDirectly(lineNumber);
                    if (line == null)
                        return null;

                    return new TextLine
                    {
                        LineNumber = lineNumber,
                        Content = line,
                        FilePosition = 0,
                        Length = line.Length
                    };
                }
                catch
                {
                    return null;
                }
            });
        }

        /// <summary>
        /// 直接读取指定行
        /// </summary>
        /// <param name="lineNumber">行号</param>
        /// <returns>行内容</returns>
        private string? ReadLineDirectly(int lineNumber)
        {
            if (_accessor == null) return null;

            try
            {
                // 读取文件内容到找到目标行
                long position = 0;
                int currentLine = 1;
                var lineBuffer = new List<byte>();
                
                var buffer = new byte[1024 * 1024]; // 1MB缓冲区
                long bytesRead = 0;
                
                while (bytesRead < _fileSize && currentLine <= lineNumber)
                {
                    int bytesToRead = (int)Math.Min(buffer.Length, _fileSize - bytesRead);
                    _accessor.ReadArray(bytesRead, buffer, 0, bytesToRead);
                    
                    for (int i = 0; i < bytesToRead; i++)
                    {
                        if (buffer[i] == '\n' || buffer[i] == '\r')
                        {
                            if (currentLine == lineNumber)
                            {
                                // 找到目标行，解码并返回
                                var bytes = lineBuffer.ToArray();
                                return _currentEncoding.GetString(bytes);
                            }
                            
                            currentLine++;
                            lineBuffer.Clear();
                            
                            // 跳过 \r\n 组合
                            if (buffer[i] == '\r' && i + 1 < bytesToRead && buffer[i + 1] == '\n')
                            {
                                i++;
                            }
                        }
                        else if (currentLine == lineNumber)
                        {
                            lineBuffer.Add(buffer[i]);
                        }
                    }
                    
                    bytesRead += bytesToRead;
                }
                
                // 处理最后一行
                if (currentLine == lineNumber && lineBuffer.Count > 0)
                {
                    var bytes = lineBuffer.ToArray();
                    return _currentEncoding.GetString(bytes);
                }
                
                return null;
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 获取多行（优化版本）
        /// </summary>
        /// <param name="startLine">起始行号</param>
        /// <param name="count">行数</param>
        /// <returns>文本行列表</returns>
        public async Task<List<TextLine>> GetLinesAsync(int startLine, int count)
        {
            if (!IsFileOpen || startLine < 1 || startLine > TotalLines)
                return new List<TextLine>();

            return await Task.Run(() =>
            {
                var lines = new List<TextLine>();
                var buffer = new byte[1024 * 1024]; // 1MB缓冲区
                long bytesRead = 0;
                int currentLine = 1;
                var lineBuffer = new List<byte>();
                
                while (bytesRead < _fileSize && lines.Count < count)
                {
                    int bytesToRead = (int)Math.Min(buffer.Length, _fileSize - bytesRead);
                    _accessor.ReadArray(bytesRead, buffer, 0, bytesToRead);
                    
                    for (int i = 0; i < bytesToRead; i++)
                    {
                        if (buffer[i] == '\n' || buffer[i] == '\r')
                        {
                            // 如果当前行在目标范围内，添加到结果
                            if (currentLine >= startLine && currentLine < startLine + count)
                            {
                                var lineBytes = lineBuffer.ToArray();
                                var content = _currentEncoding.GetString(lineBytes);
                                lines.Add(new TextLine
                                {
                                    LineNumber = currentLine,
                                    Content = content,
                                    FilePosition = bytesRead + i - lineBuffer.Count,
                                    Length = content.Length
                                });
                            }
                            
                            currentLine++;
                            lineBuffer.Clear();
                            
                            // 跳过 \r\n 组合
                            if (buffer[i] == '\r' && i + 1 < bytesToRead && buffer[i + 1] == '\n')
                            {
                                i++;
                            }
                        }
                        else if (currentLine >= startLine && currentLine < startLine + count)
                        {
                            lineBuffer.Add(buffer[i]);
                        }
                    }
                    
                    bytesRead += bytesToRead;
                }
                
                // 处理最后一行
                if (currentLine >= startLine && currentLine < startLine + count && lineBuffer.Count > 0)
                {
                    var lineBytes = lineBuffer.ToArray();
                    var content = _currentEncoding.GetString(lineBytes);
                    lines.Add(new TextLine
                    {
                        LineNumber = currentLine,
                        Content = content,
                        FilePosition = bytesRead - lineBuffer.Count,
                        Length = content.Length
                    });
                }
                
                return lines;
            });
        }

        /// <summary>
        /// 重新加载文件（使用新编码）
        /// </summary>
        /// <param name="encoding">新编码</param>
        public async Task<bool> ReloadWithEncodingAsync(Encoding encoding)
        {
            if (string.IsNullOrEmpty(FilePath))
                return false;

            var oldEncoding = _currentEncoding;
            _currentEncoding = encoding;

            try
            {
                await OpenFileAsync(FilePath, encoding);
                OnEncodingChanged(new EncodingChangedEventArgs(oldEncoding, encoding));
                return true;
            }
            catch
            {
                _currentEncoding = oldEncoding;
                return false;
            }
        }

        /// <summary>
        /// 关闭文件
        /// </summary>
        public void CloseFile()
        {
            _accessor?.Dispose();
            _mmf?.Dispose();
            _accessor = null;
            _mmf = null;
            TotalLines = -1;
            _linePositions.Clear();
            _lineLengths.Clear();
            _linePositionsBuilt = false;
            _cachedContent = null; // 清除缓存
        }

        /// <summary>
        /// 触发文件打开事件
        /// </summary>
        protected virtual void OnFileOpened(FileOpenedEventArgs e)
        {
            FileOpened?.Invoke(this, e);
        }

        /// <summary>
        /// 触发编码改变事件
        /// </summary>
        protected virtual void OnEncodingChanged(EncodingChangedEventArgs e)
        {
            EncodingChanged?.Invoke(this, e);
        }

        public void Dispose()
        {
            if (!_disposed)
            {
                CloseFile();
                _disposed = true;
            }
        }
    }
}
